package com.example.parametervalidator.aspect;

import com.example.parametervalidator.entity.AnnotationInterceptorRegistration;
import com.example.parametervalidator.entity.ParameterBean;
import com.example.parametervalidator.validator.core.DefaultParameterValidator;
import com.example.parametervalidator.validator.core.processor.ValidAnnotationProcessor;
import com.example.parametervalidator.validator.core.processor.constraintAnnotation.DefaultConstraintAnnotationProcessor;
import com.example.parametervalidator.validator.result.ParameterValidatorResult;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
@Aspect
public class ValidInterceptor {


    @Autowired
    private ValidAnnotationProcessor validAnnotationProcessor;


    @Autowired
    private DefaultConstraintAnnotationProcessor defaultConstraintAnnotationProcessor;

    @Autowired
    private DefaultParameterValidator defaultParameterValidator;


    @Pointcut("@annotation(com.example.parametervalidator.annotation.Validator)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object valid(ProceedingJoinPoint joinPoint) throws Throwable {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        //解析注解获取参数注解的classes类
        Map<Object, Class> classMap = validAnnotationProcessor.getParamteClass(targetMethod, joinPoint.getArgs());
        //说一下参数，我现在拥有classes，和 target,
        //我现在需要解析 实例对象上面的注解，是否存在，是啥注解，并封装在ParameterBean中。
        //遍历classes 反射解析约束注解。
        List<ParameterValidatorResult> parameterValidatorResults = new ArrayList<>();
        for (Object key :
                classMap.keySet()) {
            ParameterBean parameterBean = defaultConstraintAnnotationProcessor.defaultAnalysisAnnotation(classMap.get(key), key);
            //TODO 解析ParameterBean 返回 Result
            ParameterValidatorResult res = defaultParameterValidator.validateParameter(parameterBean);
            if (res != null) {
                parameterValidatorResults.add(res);
            }
        }
        //TODO 归并结果
        if (parameterValidatorResults.size() > 0) {
            for (ParameterValidatorResult result :
                    parameterValidatorResults) {
                //拥有无效参数，处理无效参数打印结果。
                if (result.hasInvalidParameter()) {
                    return result.errorDesc().get(0);
                }
            }
        }
        return joinPoint.proceed();
    }


}
